package com.serena.da.rest.services.deploy;

import org.json.JSONArray;
import org.json.JSONObject;
import com.serena.da.rest.common.GlobalContext;
import com.serena.da.rest.common.Utils;
import com.serena.da.rest.http_helpers.Response;
import com.serena.da.rest.services.plugin.SraPluginService;
import com.serena.da.rest.services.security.SraSecurityService;

import java.util.HashMap;
import java.util.Iterator;

/**
 * Created by Spitkovskyi Igor on 8/2/2014.
 */
public class ComponentService extends SraDeployService {
    private static ComponentService componentService;

    private final String METHOD_COMPONENT = "component/";
    private final String METHOD_COMPONENT_PROCESS = "componentProcess/";
    private final String METHOD_COMPONENT_TEMPLATE = "componentTemplate/";

    private ComponentService() throws Exception {
        super();
    }

    public static ComponentService getInstance() throws Exception {
        if (componentService == null) {
            componentService = new ComponentService();
        }
        return componentService;
    }

    private String getRestUrlComponent() {
        return getRestUrl(METHOD_COMPONENT);
    }

    private String getRestUrlComponentTemplate() {
        return getRestUrl(METHOD_COMPONENT_TEMPLATE);
    }

    private String getRestUrlComponentProcess() {
        return getRestUrl(METHOD_COMPONENT_PROCESS);
    }

    //GET COMPONENT
    public String getComponent(String ComponentID) throws Exception {
        String componentInfo = "";

        if (ComponentID.isEmpty()) {
            throw new Exception("Cannot get component information. No component ID is provided.");
        }
        String restCallUrl = getRestUrlComponent() + ComponentID;

        //This approach with adding user/password directly to URL works!
        //HttpGet getRequest = Request.GET(restCallUrl);
        //GetRequest getRequest = new GetRequest(restCallUrl);
        try {
            componentInfo = executeRequest(restCallUrl, "GET", null, null, GlobalContext.COMPT_PREFIX).getResponseBody();
        } catch (Exception e) {
            System.out.println("Error on attempt to execute 'getComponent' method");
        }

        return componentInfo;
    }

    public String getComponentIdByName(String componentName) throws Exception {
        JSONArray allComponents = getAllExistingItems(getRestUrlComponent());
        return getItemIdByName(componentName, allComponents);
        /*
        String id = null;

        for (int i = 0; i < allComponents.length() && id == null; i++) {
            JSONObject component = allComponents.getJSONObject(i);
            String name = component.getString("name");
            if (name.equals(componentName)) {
                id = component.getString("id");
            }
        }

        if (id == null) {
            throw new Exception("Component not found: " + componentName);
        }

        GlobalContext.Put(GlobalContext.COMPT_PREFIX + componentName, id);

        return id;
        */
    }

    public String getComponentTemplateIdByName(String componentTemplateName) throws Exception {
        JSONArray allComponentTemplates = getAllExistingItems(getRestUrlComponentTemplate());
        return getItemIdByName(componentTemplateName, allComponentTemplates);
    }

    //CREATE COMPONENT (FILE SYSTEM BASIC TYPE)
    public boolean createComponent(HashMap<String, String> typeSpecificParameters, HashMap<String, String> commonParameters) throws Exception {
        //GET TEMPLATES: http://localhost:8081/serena_ra/rest/deploy/componentTemplate;  Find if there's template specified in test parameters.
        Response response;
        boolean creationSuccess = false;
        String restUrl = getRestUrlComponent();

        //Find templateID and set instead of template name into the parameters HashMap
        if(!commonParameters.get("compTemplateId").isEmpty()){
            String templateId = getComponentTemplateIdByName(commonParameters.get("compTemplateId"));
            commonParameters.put("compTemplateId", templateId);
        }

        JSONObject json = getCreateComponentJSON(typeSpecificParameters, commonParameters);

        if(!Boolean.parseBoolean(json.getString("runVersionCreationProcess"))){
            json.remove("versionCreationProcessId");
            json.remove("versionCreationEnvironmentId");
        }

        try {
            response = executeRequest(restUrl, Method.PUT, json.toString(), GlobalContext.COMPT_PREFIX);
            creationSuccess = response.getSuccess();
            if (creationSuccess) {
                printReturnedInformation("Component: ", response.getResponseBody());
            }
        } catch (Exception e) {
            e.printStackTrace();
            return creationSuccess;
        }
        return creationSuccess;
    }

    private JSONObject getCreateComponentJSON(HashMap<String, String> replaceTypeSpecificParameters, HashMap<String, String> replaceCommonParameters) {
        String compConfigType = replaceCommonParameters.get("compConfigType");

        final String commonParametersFile = "CommonParameters.js";
        final String pathToTemplates = "Components/createComponent/";

        //Load JSON from type-specific template and replace parameters.
        String pathToTypeSpecificParamsTemplate = "Components/createComponent/" + compConfigType + ".js";
        String typeSpecificJson = Utils.replaceJsonTemplateKeys(pathToTypeSpecificParamsTemplate, replaceTypeSpecificParameters);

        //Load JSON from common template and add to type-specific structure.
        String pathToCommonParamsTemplate = pathToTemplates + commonParametersFile;
        String commonJson = Utils.replaceJsonTemplateKeys(pathToCommonParamsTemplate, replaceCommonParameters);

        //Merge common parameters with type-specific parameters
        Iterator itr;
        JSONObject commonParameters = new JSONObject(commonJson);
        JSONObject typeSpecificParameterss = new JSONObject(typeSpecificJson);

        //Merge all common PARAMETERS into type-specific parameters JSONObject
        JSONObject mergedJson = Utils.mergeJSONObjects(commonParameters, typeSpecificParameterss);

        return mergedJson;
    }


    //CREATE COMPONENT PROCESS
    public boolean createComponentProcess(String ParentComponentName, String ProcessName, String ProcessDescription, String ProcessType,
                                          String RequiredComponentRole) throws Exception {
        Response response;
        boolean creationSuccess;
        String restUrl = getRestUrlComponentProcess();      //getRestUrl(COMPONENT_PROCESS_SERVICE);
        String componentID = GlobalContext.getComponentID(ParentComponentName); //Get(COMPT_PREFIX + ParentComponentName).toString(); //service.getEntityIDbyNameFromGlobalContext(COMPT_PREFIX, CompName);//IMPROVE: Maybe do not store this method in Rest basic classes?
        if (componentID.isEmpty()) {
            return false;
        }

        //PutRequest putReq = new PutRequest(restUrl);
        try {
            String json = getCreateComponentProcessJSON(ProcessName, ProcessDescription, componentID, ProcessType, RequiredComponentRole);
            response = executeRequest(restUrl, Method.PUT, json, GlobalContext.COMPT_PROCESS_PREFIX);
            creationSuccess = response.getSuccess();
            if (creationSuccess) {
                printReturnedInformation("Component process: ", response.getResponseBody());
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return creationSuccess;
    }

    //CREATE COMPONENT PROCESS WORKFLOW
    public boolean createComponentProcessWorkflow(String ComponentName, String ProcessName, String StepNames, String PluginNames,
                                                  String CommandNames) throws Exception {
        String SAVE_WORKFLOW_ACTION = "/saveActivities";
        Response response;
        boolean creationSuccess;

        String workflowName;
        String componentProcessID = GlobalContext.getComponentProcessID(ProcessName);  //Get(COMPT_PROCESS_PREFIX + ProcessName).toString();
        String componentID = GlobalContext.getComponentID(ComponentName); //Get(COMPT_PREFIX + ComponentName).toString();

        String restUrl = getRestUrlComponentProcess() + componentProcessID + SAVE_WORKFLOW_ACTION;

        //Get version of the latest component process workflow
        //PutRequest putReq = new PutRequest(restUrl);
        try {
//            for (int i = 0; i < Quantity; i++) {
            //String workflowNameSource = getIteratedName((ComponentName + ProcessName + StepNames + PluginNames + CommandNames + componentProcessID), i);
            String workflowNameSource = ComponentName + ProcessName + StepNames + PluginNames + CommandNames + componentProcessID;

            //Convert specified string parameters to MD5 and use value as workflow name
            workflowName = Utils.getMD5(workflowNameSource);

            //Determine current version count
            int workflowVersionsCount = getComponentWorkflowVersionsCount(componentID, componentProcessID); //DONT close connection on complete
            //putReq.setHeader(new BasicHeader("componentProcessVersion", "" + (workflowVersionsCount)));  //IMPROVE: Where should it be?

            //Compose JSON for posting workflow
            String json = getCreateComponentProcessMultistepWorkflowJSON(workflowName, PluginNames, CommandNames, StepNames);

            HashMap<String, String> headers = new HashMap<String, String>();
            headers.put("componentProcessVersion", "" + (workflowVersionsCount));

            response = executeRequest(restUrl, Method.PUT, json, headers);
            creationSuccess = response.getSuccess();
            if (creationSuccess) {
                printReturnedInformation("Component process workflow: ", response.getResponseBody());
            }
//            }
        } catch (Exception e) {
            e.printStackTrace();
            creationSuccess = false;
        }

        return creationSuccess;
    }


    //GET NUMBER OF EXISTING WORKFLOWS IN SPECIFIED COMPONENT PROCESS
    private int getComponentWorkflowVersionsCount(String ComponentID, String ComponentProcessID) throws Exception {
        String COMPONENT_PROCESSES_WITH_VERSIONS = "/processesWithVersion";

        //  http://localhost:8081/serena_ra/rest/deploy/component/09c35624-376b-4377-bd56-521d7e26dff5/fullProcesses/active
        String url = getRestUrlComponent() + ComponentID + COMPONENT_PROCESSES_WITH_VERSIONS;
        return getWorkflowVersionsCount(url, ComponentProcessID);
    }

    //CREATE COMPONENT PROCESS WORKFLOW
    private String getCreateComponentProcessMultistepWorkflowJSON(String workflowName, String PluginNames, String CommandNames, String StepNames) throws Exception {
        String workflowBody = "{" +
                "\"type\" : \"graph\"," +
                "\"children\" : [{" +
                "\"type\" : \"finish\"," +
                "\"name\" : \"" + workflowName + "\"" +  //e23f517a2abe52b265a12c7ac322c9
                "},";

        String pluginStepsArrayCloser = "], ";

        String workflowFooter = "}";

        SraPluginService p_service;

        String[] pluginNames = PluginNames.split(";");
        String[] commandNames = CommandNames.split(";");
        String[] stepNames = StepNames.split(";");

        //Move OUT this logic from here. It should be done somewhere up. Here it should expect HashMap <String, StepContent>. See similar done for ApplicationProcessWorkflow
        if (pluginNames.length != commandNames.length || pluginNames.length != stepNames.length) {
            throw new Exception("Unequal number of plugin/command/step names provided. In the given implementation there should be equal number of plugin names, command names and step names provided.");
        }

        if (stepNames.length < 1) {
            throw new Exception("No plugins and/or command names and/or step names are provided.");
        }

        //p_service = new SraPluginService(host, port, user, pwd);
        p_service = SraPluginService.getInstance();

        int numberOfSteps = stepNames.length;

        for (int i = 0; i < numberOfSteps; i++) {
            //Get all needed info about plugin
            //p_service = new SraPluginService(host, port, user, pwd);
            HashMap pluginInfo = null;
            String commandID = "";
            try {
                //Get information about plugin whose step will be used.
                pluginInfo = p_service.getAutomationPluginInfoByName(pluginNames[i]);
                //Get ID of plugin step
                commandID = p_service.getPluginCommandID(pluginInfo.get("id").toString(), commandNames[i]);
            } catch (Exception e) {
                e.printStackTrace();
            }

            if (pluginInfo == null || commandID.isEmpty()) {
                throw new Exception("Could not get information required to submit component_process_workflow.");
            }

            //Following code is bad. Think of having classes implementing particular plugins or plugin steps
            //Get JSON of plugin-step to be used for current (based on loop index "i") plugin/command
            if (commandNames[i].equalsIgnoreCase("Upload Artifacts")) {
                workflowBody = workflowBody + getUploadArtifactsJSON(pluginNames[i], pluginInfo.get("id").toString(), pluginInfo.get("pluginId").toString(), pluginInfo.get("version").toString(),
                        pluginInfo.get("versionNumber").toString(), pluginInfo.get("ghostedDate").toString(), commandNames[i], commandID, stepNames[i]);
            } else if (commandNames[i].equalsIgnoreCase("Download Artifacts")) {
                //method to be implemented
                workflowBody = workflowBody + getDownloadArtifactsJSON(pluginNames[i], pluginInfo.get("id").toString(), pluginInfo.get("pluginId").toString(), pluginInfo.get("version").toString(),
                        pluginInfo.get("versionNumber").toString(), pluginInfo.get("ghostedDate").toString(), commandNames[i], commandID, stepNames[i]);
            }
            //Append comma to the plugin-JSON block, if not last in the array
            if (i < stepNames.length - 1) {
                workflowBody = workflowBody + ", ";
            }
            //Append steps array closer, geometry section and json footer
            if (i == stepNames.length - 1) {
                workflowBody = workflowBody +
                        pluginStepsArrayCloser +
                        getWorkflowGeometrySection(stepNames, workflowName) +
                        workflowFooter;
            }
        }
        return workflowBody;
    }

    private String getUploadArtifactsJSON(String pluginName, String pluginID, String pluginIdString, String pluginVersion, String pluginVersionNumber, String ghostDate,
                                          String commandName, String commandID, String workflowStepName) {
        return getUploadArtifactsJSON(pluginName, pluginID, pluginIdString, pluginVersion, pluginVersionNumber, ghostDate, commandName, commandID, workflowStepName, "genericTestValue", "genericTestValue");
    }

    private String getUploadArtifactsJSON(String pluginName, String pluginID, String pluginIdString, String pluginVersion, String pluginVersionNumber, String ghostDate,
                                          String commandName, String commandID, String workflowStepName, String UserParameter, String ChangeCommentParameter) {
        return "{" +
                "\"type\" : \"plugin\"," +
                "\"name\" : \"" + workflowStepName + "\"," +  //my_upload_artifacts
                "\"commandName\" : \"" + commandName + "\"," +  //Upload Artifacts
                "\"pluginName\" : \"" + pluginName + "\"," +      //Serena RA Versioned File Storage
                "\"pluginVersion\" : " + pluginVersionNumber + "," +  //16
                "\"command\" : {" +
                "\"id\" : \"" + commandID + "\"," +      //a0a52bc0-9414-44bb-9b20-04b387760ae6
                "\"name\" : \"" + commandName + "\"," + //Upload Artifacts
                "\"description\" : \"Upload artifacts to a VFS server.\"," +
                "\"plugin\" : {" +
                "\"id\" : \"" + pluginID + "\"," +       //ceb13bc0-4471-454d-958f-b7cf7d3fa6fd
                "\"pluginId\" : \"" + pluginIdString + "\"," +      //com.urbancode.plugin.VFS
                "\"name\" : \"" + pluginName + "\"," +            //Serena RA Versioned File Storage
                "\"description\" : \"A plugin to allow Serena RA to upload artifacts to a Serena RA (VFS) artifact repository.\"," +
                "\"version\" : \"" + pluginVersion + "\"," +           //16_119
                "\"versionNumber\" : " + pluginVersionNumber + "," +  //16
                "\"ghostedDate\" : " + ghostDate + "" +         //0
                "}," +
                "\"properties\" : [{" +
                "\"name\" : \"repositoryUrl\"," +
                "\"type\" : \"TEXT\"," +
                "\"value\" : \"${p:server.url}/vfs\"," +
                "\"required\" : true," +
                "\"hidden\" : true," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"repositoryId\"," +
                "\"type\" : \"TEXT\"," +
                "\"value\" : \"${p:component/code_station/repository}\"," +
                "\"required\" : true," +
                "\"hidden\" : true," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"label\"," +
                "\"type\" : \"TEXT\"," +
                "\"value\" : \"${p:version.name}\"," +
                "\"required\" : true," +
                "\"hidden\" : true," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"changeUser\"," +
                "\"label\" : \"User\"," +
                "\"type\" : \"TEXT\"," +
                "\"value\" : \"\"," +
                "\"required\" : true," +
                "\"description\" : \"The name of the user making the change.\"," +
                "\"hidden\" : false," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"changeComment\"," +
                "\"label\" : \"Comment\"," +
                "\"type\" : \"TEXT\"," +
                "\"value\" : \"\"," +
                "\"required\" : true," +
                "\"description\" : \"The comment for the change.\"," +
                "\"hidden\" : false," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"update\"," +
                "\"label\" : \"Update\"," +
                "\"type\" : \"CHECKBOX\"," +
                "\"value\" : \"\"," +
                "\"required\" : false," +
                "\"description\" : \"Create a new changeset on top of old instead of completely new one\"," +
                "\"hidden\" : false," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"directoryOffset\"," +
                "\"label\" : \"Directory Offset\"," +
                "\"type\" : \"TEXT\"," +
                "\"value\" : \".\"," +
                "\"required\" : true," +
                "\"description\" : \"The working directory to use when executing this command. This is relative to current working directory.\"," +
                "\"hidden\" : false," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"fileIncludePatterns\"," +
                "\"label\" : \"Includes\"," +
                "\"type\" : \"TEXTAREA\"," +
                "\"value\" : \"**/*\"," +
                "\"required\" : true," +
                "\"description\" : \"The patterns to match files to upload. The wildcard ** indicates every directory and the wildcard * indicates every file. So the pattern dist/**/* would retrieve the entire file tree underneath the dist directory.\"," +
                "\"hidden\" : false," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"fileExcludePatterns\"," +
                "\"label\" : \"Excludes\"," +
                "\"type\" : \"TEXTAREA\"," +
                "\"value\" : \"\"," +
                "\"required\" : false," +
                "\"description\" : \"The patterns to exclude files to upload.\"," +
                "\"hidden\" : false," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"saveFileExecuteBits\"," +
                "\"label\" : \"Save File Execute Bits\"," +
                "\"type\" : \"CHECKBOX\"," +
                "\"value\" : \"false\"," +
                "\"required\" : false," +
                "\"description\" : \"When enabled, file execute bits are saved with the files.\"," +
                "\"hidden\" : false," +
                "\"allowedValues\" : []" +
                "}" +
                "]" +
                "}," +
                "\"properties\" : {" +
                "\"repositoryUrl\" : \"${p:server.url}/vfs\"," +
                "\"repositoryId\" : \"${p:component/code_station/repository}\"," +
                "\"label\" : \"${p:version.name}\"," +
                "\"changeUser\" : \"" + UserParameter + "\"," +
                "\"changeComment\" : \"" + ChangeCommentParameter + "\"," +
                "\"update\" : \"false\"," +
                "\"directoryOffset\" : \".\"," +
                "\"fileIncludePatterns\" : \"**/*\"," +
                "\"fileExcludePatterns\" : \"\"," +
                "\"saveFileExecuteBits\" : \"false\"" +
                "}," +
                "\"allowFailure\" : \"false\"," +
                "\"useImpersonation\" : false," +
                "\"impersonationGroup\" : \"\"," +
                "\"impersonationPassword\" : \"\"," +
                "\"impersonationUseSudo\" : false," +
                "\"impersonationUseSsh\" : false," +
                "\"workingDir\" : \"\"," +
                "\"preconditionScript\" : \"\"," +
                "\"postProcessingScript\" : \"\"," +
                "\"showHidden\" : false" +
                "}";
    }

    private String getDownloadArtifactsJSON(String pluginName, String pluginID, String pluginIdString, String pluginVersion, String pluginVersionNumber, String ghostDate,
                                            String commandName, String commandID, String workflowStepName) {
        return "{" +
                "\"type\" : \"plugin\"," +
                "\"name\" : \"" + workflowStepName + "\"," +  //my_download_artifacts
                "\"commandName\" : \"" + commandName + "\"," +  //Download Artifacts
                "\"pluginName\" : \"" + pluginName + "\"," +      //Serena RA Versioned File Storage
                "\"pluginVersion\" : " + pluginVersionNumber + "," +  //16
                "\"command\" : {" +
                "\"id\" : \"" + commandID + "\"," +      //4cc9d2f2-16fd-4eb4-899b-95da5083a35b
                "\"name\" : \"" + commandName + "\"," + //Download Artifacts
                "\"description\" : \"Download artifacts from a VFS server.\"," +
                "\"plugin\" : {" +
                "\"id\" : \"" + pluginID + "\"," +       //b431e3fc-3c82-4ec8-b0a0-1af5e5530968
                "\"pluginId\" : \"" + pluginIdString + "\"," +      //com.urbancode.plugin.VFS
                "\"name\" : \"" + pluginName + "\"," +            //Serena RA Versioned File Storage
                "\"description\" : \"A plugin to allow Serena RA to upload artifacts to a Serena RA (VFS) artifact repository.\"," +
                "\"version\" : \"" + pluginVersion + "\"," +           //16_119
                "\"versionNumber\" : " + pluginVersionNumber + "," +  //16
                "\"ghostedDate\" : " + ghostDate + "" +         //0
                "}," +
                "\"properties\" : [{" +
                "\"name\" : \"directoryOffset\"," +
                "\"label\" : \"Directory Offset\"," +
                "\"type\" : \"TEXT\"," +
                "\"value\" : \".\"," +
                "\"required\" : true," +
                "\"description\" : \"The working directory to use when executing this command. This is relative to current working directory.\"," +
                "\"hidden\" : false," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"fileIncludePatterns\"," +
                "\"label\" : \"Includes\"," +
                "\"type\" : \"TEXTAREA\"," +
                "\"value\" : \"**/*\"," +
                "\"required\" : true," +
                "\"description\" : \"The patterns to match files to upload. The wildcard ** indicates every directory and the wildcard * indicates every file. So the pattern dist/**/* would retrieve the entire file tree underneath the dist directory.\"," +
                "\"hidden\" : false," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"fileExcludePatterns\"," +
                "\"label\" : \"Excludes\"," +
                "\"type\" : \"TEXTAREA\"," +
                "\"value\" : \"\"," +
                "\"required\" : false," +
                "\"description\" : \"The patterns to exclude files to upload.\"," +
                "\"hidden\" : false," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"syncMode\"," +
                "\"label\" : \"Sync Mode\"," +
                "\"type\" : \"SELECT\"," +
                "\"value\" : \"true\"," +
                "\"required\" : false," +
                "\"description\" : \"Sync transfers only changed files, removing files that exist only in the previously deployed version. Clean removes all files not contained in the currently deployed version\"," +
                "\"hidden\" : false," +
                "\"allowedValues\" : [{" +
                "\"label\" : \"none\"," +
                "\"value\" : \"false\"" +
                "}, {" +
                "\"label\" : \"Sync\"," +
                "\"value\" : \"true\"" +
                "}, {" +
                "\"label\" : \"Sync and Clean\"," +
                "\"value\" : \"FULL\"" +
                "}" +
                "]" +
                "}, {" +
                "\"name\" : \"fullVerification\"," +
                "\"label\" : \"Full Verification\"," +
                "\"type\" : \"CHECKBOX\"," +
                "\"value\" : \"true\"," +
                "\"required\" : false," +
                "\"description\" : \"(Valid only with Sync Mode enabled) When selected, hashes will be computed on each file in the destination artifact set to determine whether network transfer is necessary. Otherwise, files will be compared by date modified and size.\"," +
                "\"hidden\" : false," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"setFileExecuteBits\"," +
                "\"label\" : \"Set File Execute Bits\"," +
                "\"type\" : \"CHECKBOX\"," +
                "\"value\" : \"false\"," +
                "\"required\" : false," +
                "\"description\" : \"When enabled, sets file execute bits on the files which have them set in the repository.\"," +
                "\"hidden\" : false," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"verifyFileIntegrity\"," +
                "\"label\" : \"Verify File Integrity\"," +
                "\"type\" : \"CHECKBOX\"," +
                "\"value\" : \"false\"," +
                "\"required\" : false," +
                "\"description\" : \"When enabled, verifies downloaded files match their hash. Enabling this may reduce performance.\"," +
                "\"hidden\" : false," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"repositoryUrl\"," +
                "\"type\" : \"TEXT\"," +
                "\"value\" : \"${p:server.url}/vfs\"," +
                "\"required\" : true," +
                "\"hidden\" : true," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"repositoryId\"," +
                "\"type\" : \"TEXT\"," +
                "\"value\" : \"${p:component/code_station/repository}\"," +
                "\"required\" : true," +
                "\"hidden\" : true," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"label\"," +
                "\"type\" : \"TEXT\"," +
                "\"value\" : \"${p:version.name}\"," +
                "\"required\" : true," +
                "\"hidden\" : true," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"serverUrl\"," +
                "\"type\" : \"TEXT\"," +
                "\"value\" : \"${p:server.url}\"," +
                "\"required\" : false," +
                "\"hidden\" : true," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"compId\"," +
                "\"type\" : \"TEXT\"," +
                "\"value\" : \"${p:component.id}\"," +
                "\"required\" : false," +
                "\"hidden\" : true," +
                "\"allowedValues\" : []" +
                "}, {" +
                "\"name\" : \"resId\"," +
                "\"type\" : \"TEXT\"," +
                "\"value\" : \"${p:resource.id}\"," +
                "\"required\" : false," +
                "\"hidden\" : true," +
                "\"allowedValues\" : []" +
                "}" +
                "]" +
                "}," +
                "\"properties\" : {" +
                "\"directoryOffset\" : \".\"," +
                "\"fileIncludePatterns\" : \"**/*\"," +
                "\"fileExcludePatterns\" : \"\"," +
                "\"syncMode\" : \"true\"," +
                "\"fullVerification\" : \"true\"," +
                "\"setFileExecuteBits\" : \"false\"," +
                "\"verifyFileIntegrity\" : \"false\"," +
                "\"repositoryUrl\" : \"${p:server.url}/vfs\"," +
                "\"repositoryId\" : \"${p:component/code_station/repository}\"," +
                "\"label\" : \"${p:version.name}\"," +
                "\"serverUrl\" : \"${p:server.url}\"," +
                "\"compId\" : \"${p:component.id}\"," +
                "\"resId\" : \"${p:resource.id}\"" +
                "}," +
                "\"allowFailure\" : \"false\"," +
                "\"useImpersonation\" : false," +
                "\"impersonationGroup\" : \"\"," +
                "\"impersonationPassword\" : \"\"," +
                "\"impersonationUseSudo\" : false," +
                "\"impersonationUseSsh\" : false," +
                "\"workingDir\" : \"\"," +
                "\"preconditionScript\" : \"\"," +
                "\"postProcessingScript\" : \"\"," +
                "\"showHidden\" : false" +
                "}";
    }


    //CREATE COMPONENT PROCESS JSON
    private String getCreateComponentProcessJSON(String processName, String processDescr, String componentID, String processType,
                                                 String RequiredComponentRole) throws Exception {
        String status = "Active";
        String defaultWorkingDir = "${p:resource/work.dir}/${p:component.name}";
        boolean takesVersion = true;

        String templateFile = "/json_templates/Components/createComponentProcess/CreateComponentProcess.js";
        JSONObject componentProcess = getJsonFromFile(templateFile);

        /*"inventoryActionType" parameter is valid for processes of "Deployment", "Uninstall" types*/
        if (processType.equalsIgnoreCase("deployment")) {
            componentProcess.put("inventoryActionType", "ADD");
            componentProcess.put("configActionType", "ADD");
        } else if (processType.equalsIgnoreCase("uninstall")) {
            componentProcess.put("inventoryActionType", "REMOVE");
            componentProcess.remove("configActionType");
        } else if (processType.equalsIgnoreCase("configuration deployment")) {
            componentProcess.put("configActionType", "ADD");
            componentProcess.remove("inventoryActionType");
        }

        if (!RequiredComponentRole.isEmpty()) {
            //SraSecurityService s_service = new SraSecurityService(host, port, user, pwd);
            SraSecurityService s_service = SraSecurityService.getInstance();
            String roleID = s_service.getSecurityRoleID("Components", RequiredComponentRole);
            componentProcess.put("componentRoleId", roleID);

        }

        componentProcess.put("name", processName);
        componentProcess.put("description", processDescr);
        componentProcess.put("status", status);
        componentProcess.put("defaultWorkingDir", defaultWorkingDir);
        componentProcess.put("componentId", componentID);
        componentProcess.put("takesVersion", takesVersion);

        //return getCreateComponentProcessJSON(processName, processDescr, status, defaultWorkingDir, componentID, inventoryActionType, configActionType, takesVersion);
        return componentProcess.toString();
    }

    public Response importVersion(String id, String sourceConfigType, HashMap<String, String> hashMap) throws Exception {
        String url = getRestUrlComponent() + id + "/integrate";
        String pathToTemplate = "Components/importComponentVersion/" + sourceConfigType + ".js";
        String importJson = Utils.replaceJsonTemplateKeys(pathToTemplate, hashMap);

        return executeRequest(url, Method.PUT, importJson);
    }

    public class SourceConfigType {
        /* POSSIBLE COMPONENT TYPES
        "AnthillPro"
        "ClearCaseUCM"
        "Dimensions"
         "File System (Basic)"
        "File System (Versioned)"
        "Git"
        "Jenkins"
        "Luntbuild"
        "Maven"
        "PVCS"
        "Perforce"
        "StarTeam"
        "Subversion"
        "TFS"
        "TFS_SCM"
        "TeamCity"
        "TeamForge"
        "uBuild"
        * */
        public static final String FileSystemVersioned = "File System (Versioned)";
        public static final String FileSystemBasic = "File System (Basic)";
        public static final String Jenkins = "Jenkins";
        public static final String Git = "Git";
    }
}
